#ifndef _RETRO_MAPEDITOR
#define _RETRO_MAPEDITOR

#define RETRO_MAPEDITORCLASS _T("Retro.MapEditor")

namespace Retro
{
  namespace Creator
  {
    namespace Editor
    {
      enum SelectMode
      {
        SelectModeNone,
        SelectModeSelect,
        SelectModeDrag,
        SelectModeCopy,
        SelectModeResize,
        SelectModeRotate,
        SelectModeAdd,
      };

      enum Anchor
      {
        AnchorNone,
        AnchorNW,
        AnchorNE,
        AnchorSW,
        AnchorSE,
        AnchorAxisX,
        AnchorAxisY,
        AnchorFirst         = AnchorNW,
        AnchorLast          = AnchorAxisY,
        AnchorCardinalFirst = AnchorNW,
        AnchorCardinalLast  = AnchorSE,
      };

      enum MapDisplay
      {
        MapDisplayNone,
        MapDisplayAll,
        MapDisplayCurrent,
        MapDisplayShadow,
        MapDisplayFirst = MapDisplayAll,
        MapDisplayLast  = MapDisplayShadow,
      };

      enum MapItem
      {
        MapItemDisplay = EditorItemUser,
        MapItemLayer,
        MapItemTool,
        MapItemGridSize,
        MapItemToggleGrid,
        MapItemToggleIndices,
        MapItemToggleSnap,
        MapItemUser,
      };

      enum MapNotify
      {
        MapNotifyLayer = EditorNotifyUser,
        MapNotifyDisplay,
        MapNotifyTool,
        MapNotifyForeColor,
        MapNotifyGrid,
        MapNotifyUser,
      };

      enum MapTool
      {
        MapToolNone,
        MapToolSelect,
        MapToolCustom,
        MapToolFirst = MapToolSelect,
      };

      class MapEditor : public EditorBase
      {
      private:
        Device::Display::DisplayDevice* mDevice;

        MapDisplay  mDisplay;
        MapTool     mTool;
        INT         mZoom;
        INT         mGridSize;

      protected:
        static Menu  menuLayers;
        static Menu  menuDisplay;
        static Menu  menuTools;

        BOOL            mShowGrid;
        COLORREF        mForeColor;
        Geom::Bounds    mSelection;
        SelectMode      mSelectMode;
        Geom::Point     mDragPoint;
        Geom::Point     mSelectPoint;
        Geom::Bounds    mView;

        INT   mLayer;
        INT   mMapLayers;
        INT   mMapWidth;
        INT   mMapHeight;

        virtual VOID  fillMapBuffer()         = 0;
        virtual VOID  freeMapBuffer()         = 0;
        virtual VOID  createMapBuffer()       = 0;
        virtual VOID  drawBackground();
        virtual VOID  drawForeground();
        virtual VOID  drawLayer(INT layer)    = 0;

        BOOL  render(Device::Display::DisplayDevice* iDevice);
        VOID  drawGrid(INT size);
        VOID  updateLayers();
        VOID  initToolbar();
        VOID  adjustMousePos(Geom::Point &pt);

        virtual VOID  onToolbar(ToolBarNotify* iData);

        virtual VOID  onPrepareDisplay()      = 0;
        virtual VOID  onInitializeDisplay()   = 0;
        virtual VOID  onUninitializeDisplay() = 0;

        virtual VOID  onEraseBackground(Event::EraseBackgroundEvent& iEvent);
        virtual VOID  onPaint();
        virtual VOID  onCreate(Event::WndCreateEvent& iEvent);
        virtual VOID  onDestroy();
        virtual VOID  onMouseWheel(Event::MouseWheelEvent& iEvent);
        virtual VOID  onKeyDown(Event::KeyEvent& iEvent);

        static INL Menu&    getLayerMenu()
        {
          return menuLayers;
        }
        static INL Menu&    getMenuDisplay()
        {
          return menuDisplay;
        }
        static INL Menu&    getToolMenu()
        {
          return menuTools;
        }

      public:
        INL Device::Display::DisplayDevice* getDevice()
        {
          return mDevice;
        }

        virtual VOID        setZoom(INT value);
        virtual INT         getZoom();

        INL MapDisplay      getDisplay()
        {
          return mDisplay;
        }
        VOID                setDisplay(MapDisplay value);

        INL INT             getGridSize()
        {
          return mGridSize;
        }

        INL VOID            setGridSize(INT iValue)
        {
          mGridSize = iValue;
          invalidate();
        }

        INLC Geom::Bounds&  getView()
        {
          return mView;
        }
        INL VOID            setView(const Geom::Bounds& value)
        {
          mView = value;
          invalidate();
        }

        INL INT             getLayer()
        {
          return mLayer;
        }
        virtual VOID        setLayer(INT value);

        INL MapTool         getTool()
        {
          return mTool;
        }
        virtual VOID        setTool(MapTool value);

        INL COLORREF        getForeColor()
        {
          return mForeColor;
        }
        INL VOID            setForeColor(COLORREF value)
        {
          mForeColor = value;
          invalidate();
        }

        INL BOOL            getShowGrid()
        {
          return mShowGrid;
        }
        VOID                setShowGrid(BOOL value);

        INLC INT&           getMapWidth()
        {
          return mMapWidth;
        }
        INLC INT&           getMapHeight()
        {
          return mMapHeight;
        }
        INLC INT&           getMapLayers()
        {
          return mMapLayers;
        }

        INL INT             getBufferWidth()
        {
          return mDevice ? mDevice->getWidth() : 0;
        }
        INL INT             getBufferHeight()
        {
          return mDevice ? mDevice->getHeight() : 0;
        }

        virtual VOID        setResource(Data::Resource* iValue);

        INL Data::Map*      getMap()
        {
          return (Data::Map*)getResource();
        }

        virtual VOID        setBufferSize(INT cx, INT cy, INT layers) = 0;
        virtual VOID        clearCopy() = 0;
        virtual INT         getLineSize();

        static BOOL         init();
        static VOID         uninit();

        MapEditor(Data::ResourceType iType);
      };
    } // namespace Editor
  } // namespace Creator
} // namespace Retro

#endif
